﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace uTILLIty.ADExtractor.Core
{
	public class AdPropertyInfo
	{
		static readonly Regex DisplayNameRegex = new Regex(@"(?ixn)^((?<displayName>.+?)[:=])(?<expression>.+)$", RegexOptions.Compiled);
		static readonly Regex AggregatorRegex = new Regex(@"(?ixn)^(?<aggregator>[^(]+)\((?<propertyName>[^)]+)\)$", RegexOptions.Compiled);
		private string _propertyName;


		public AdPropertyInfo(string propertyName)
		{
			DisplayName = PropertyName = propertyName;
			ValueSeparator = "|";
		}

		public static AdPropertyInfo[] Parse(params string[] properties)
		{
			var list = new List<AdPropertyInfo>(properties.Length);
			list.AddRange(properties.Select(Parse));
			return list.ToArray();
		}

		public static AdPropertyInfo Parse(string property)
		{
			var pi = new AdPropertyInfo(property);

			var match = DisplayNameRegex.Match(property);
			var displayNameSet = false;
			if (match.Success)
			{
				property = pi.PropertyName = match.Groups["expression"].Value;
				pi.DisplayName = match.Groups["displayName"].Value;
				displayNameSet = true;
			}

			match = AggregatorRegex.Match(property);
			if (match.Success)
			{
				AggregationType aggregation;
				if (!Enum.TryParse(match.Groups["aggregator"].Value, true, out aggregation))
				{
					throw new Exception(string.Format(Properties.Resources.UnsupportedAggregation,
					                                  match.Groups["aggregator"].Value,
					                                  string.Join(", ", Enum.GetNames(typeof (AggregationType)))));
				}
				pi.Aggregation = aggregation;
			}

			pi.PropertyName = match.Success ? match.Groups["propertyName"].Value : property;
			if (!displayNameSet)
				pi.DisplayName = pi.PropertyName;
			return pi;
		}

		public string PropertyName
		{
			get { return _propertyName; }
			set
			{
				if (value == null)
					throw new ArgumentNullException();

				var segments = value.Split('.');
				var subPi = SubAdPropertyInfo.Parse(segments[0]);
				_propertyName = subPi.PropertyName;
				SingleValueIndex = subPi.SingleValueIndex;

				SubProperties = segments.Length == 1 ? new SubAdPropertyInfo[0] : segments.Skip(1).Select(SubAdPropertyInfo.Parse).ToArray();
			}
		}

		public string DisplayName { get; set; }
		public AggregationType Aggregation { get; set; }
		public string ValueSeparator { get; set; }
		public SubAdPropertyInfo[] SubProperties { get; set; }
		public int SingleValueIndex { get; set; }

		public override string ToString()
		{
			return DisplayName;
		}
	}
}